package com.fashiontextile.common.aspect;

import com.fashiontextile.common.annotation.RequireRole;
import com.fashiontextile.common.constant.AppConstants;
import com.fashiontextile.common.constant.TokenConstants;
import com.fashiontextile.common.exception.ForbiddenException;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.lang.reflect.Method;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Objects;

/**
 * 角色校验切面类
 *
 * @author brooke_zb
 */
@Aspect
@Component
public class RequireRoleAspect {

    @Pointcut("@annotation(com.fashiontextile.common.annotation.RequireRole) || @within(com.fashiontextile.common.annotation.RequireRole)")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        Method method = signature.getMethod();

        // 优先获取方法上的注解信息
        RequireRole requireRoleAnno = method.getAnnotation(RequireRole.class);

        // 方法上获取不到，获取类上的注解信息
        if (requireRoleAnno == null) {
            requireRoleAnno = method.getDeclaringClass().getAnnotation(RequireRole.class);
        }
        String requireRole = requireRoleAnno.value();

        // 获取请求
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();

        // 若有白名单请求头则免鉴权
        String feignToken = request.getHeader(TokenConstants.WHITE_LIST_HEADER);
        if (feignToken != null && feignToken.equals(TokenConstants.WHITE_LIST_VALUE)) {
            return joinPoint.proceed();
        }

        // 获取用户角色
        String rawUserRole = request.getHeader(TokenConstants.ROLE_HEADER);
        if (rawUserRole == null) {
            throw new ForbiddenException("您没有权限访问该链接");
        }

        // 角色对比
        String userRole = URLDecoder.decode(rawUserRole, StandardCharsets.UTF_8);
        if (userRole.equals(requireRole) || userRole.equals(AppConstants.ROLE_ADMIN)) {
            // 执行原有逻辑
            return joinPoint.proceed();
        }

        // 没有权限
        throw new ForbiddenException("您没有权限访问该链接");
    }

}
